<?php if (!defined('INDEX')) { trigger_error("Index is not defined!", E_USER_ERROR); exit(); }
/**
 * Class - instance of Bookmark
 * @package      habrabookmarks
 *
 * @author       Max Kamashev <max.kamashev@floscoeli.com>
 * @copyright    floscoeli.com ©2009
 * @license      http://opensource.org/licenses/gpl-3.0.html
 * @version      SVN: $Id: Bookmark.php 46 2009-04-21 04:54:04Z M.Kamashev $
 *
 * settings:     ts: 4 spaces, eof: lf (unix), codepage: UTF-8
 */
class Bookmark {

    /**
     * Url bookmark
     *
     * @var string
     */
    private $_url = '';

    /**
     * Title bookmark
     *
     * @var string
     */
    private $_title = '';

    /**
     * Date bookmarks (UNIX_TIMESTAMP)
     *
     * @var int
     */
    private $_date = 0;

    /**
     * Description bookmark
     *
     * @var string
     */
    private $_description = '';

    /**
     * Tags array. 
     *
     * @example array('banan', 'orange', 'strawberry')
     * @var array string
     */
    private $_tags = array();

    /**
     * Type of bookmark: Local, Internet (Intranet), Error
     *
     * @var int
     */
    private $_type = BOOKMARK_TYPE_INET;

    /**
     * Consts type of bookmarks
     */
    const BOOKMARK_TYPE_ERROR = 0;
    const BOOKMARK_TYPE_INET  = 1;
    const BOOKMARK_TYPE_LOCAL = 2;

    /**
     * Set url
     *
     * @param $url string
     * @return bool
     */
    public function setUrl($url='') {
        if (empty($url)) {
            throw new Exception("Empty URL", E_USER_WARNING);
            return FALSE;
        } else {
            //Normal url
            if (preg_match("/^(http:\/\/|ftp:\/\/)([a-zA-Z0-9]+)/", $url)) {
                $this->_type = BOOKMARK_TYPE_INET;
                $this->_url = $url;
            //Local url 
            } elseif (preg_match("/^(file:\/\/|smb:\/\/|\\\\)/", $url)) {
                $this->_type = BOOKMARK_TYPE_LOCAL;
                $this->_url = $url;
            //Url without prefix "http://"
            } elseif (preg_match("/([a-zA-Z0-9]+)\.([a-zA-Z0-9]+)/",$url)) { 
                $this->_type = BOOKMARK_TYPE_INET;
                $this->_url = 'http://'.$url;
            } else {
                throw new Exception("Wrong url \"".$url."\"", E_USER_NOTICE);
                $this->_type = BOOKMARK_TYPE_ERROR;
                return FALSE;
            }
        }
        return TRUE;
    }

    /**
     * Set Title 
     *
     * @param $title string
     * @return bool
     */
    public function setTitle($title='') {
        if (empty($title)) {
            throw new Exception("Empty title", E_USER_WARNING);
            $this->_title = '';
        } else {
            $this->_title = $title;
        }
        return TRUE;
    }

    /**
     * Set date 
     *
     * @param $date
     * @return bool
     */
    public function setDate($date = 0) {
        if ((int)$date <= 0) {
            throw new Exception("Empty date", E_USER_WARNING);
            $this->_date = time();
            return FALSE;
        } else {
            $this->_date = $date;
            return TRUE;
        }
    }

    /**
     * Set description 
     *
     * @param $description string
     * @return bool
     */
    public function setDescription($description='') {
        //TODO: Сделать проверку на безопасные теги, обрезать всё лишнее!
        $this->_description = $description;
        return TRUE;
    }

    /**
     * Set tags
     *
     * @param $tags array string
     * @return bool
     */
    public function setTags($tags = array()) {
        if (count ($tags) <= 0) {
            throw new Exception ("Tags not found", E_USER_NOTICE);
            return FALSE;
        }

        foreach ($tags as $tag) {
            if (!$this->addTag($tag)) {
                return FALSE;
            }
        }
        return TRUE;
    }

    /**
     * Add single tag
     *
     * @param $tag string
     * @return bool
     */
    public function addTag($tag = '') {
        $tag =  trim((string) $tag);
/*
        if (!preg_match("/\w/iu", $tag)) { 
            //FIXME Проверить! Теги могут содержать пробелы и символы Unicode
            throw new Exception("Tags content wrong simbols ", E_USER_WARNING);
            return FALSE;
        }
*/        
        if (!in_array(trim($tag), $this->_tags)) {
            $this->_tags[] = trim($tag);
        }
        return TRUE;
    }

    /**
     * Delete tag 
     *
     * @param $tag string
     * @return bool
     */
    public function removeTag($tag = '') {
        $key = array_search(trim((string) $tag), $this->_tags);
        if ($key) {
            unset($this->_tags[$key]);
            return true;
        } else {
            return false;
        }
    }

    /**
     * Return current URL
     *
     * @return string
     */
    public function getUrl() {
        if (empty($this->_url)) {
            throw new Exception("url is not defined", E_USER_NOTICE);
            return '';
        } else {
            return $this->_url;
        }
    }

    /**
     * Return title
     *
     * @return string
     */
    public function getTitle() {
        return $this->_title;
    }

    /**
     * Return date. If not defined, then return current timestamp
     *
     * @return int unix_timestamp
     */
    public function getDate() {
        if ((int)$this->_date > 0) {
            return $this->_date;
        } else {
            $this->_date = time();
            throw new Exception("Date is not defined. Set current time", E_USER_WARNING);
            return $this->_date;
        }
    }

    /**
     * Return description
     *
     * @return string It may contein a safe html-tags 
     */
    public function getDescription() {
        return $this->_description;
    }

    /**
     * Return array of tags || string with tags, split the specified delimiter 
     *
     * @param $is_array bool if TRUE - return array, FALSE - string
     * @param $delimiter string - Symbol(s) separate string. It makes only sense only if the returned strings
     * @return array || string
     */
    public function getTags($is_array = TRUE, $delimiter = ',') {
        if ($is_array) {
            return $this->_tags;
        } else {
            return implode($delimiter, $this->_tags);
        }
    }

    /**
     * Return constant (int) type of URL (LOCAL || INET || ERROR)
     *
     * @return int
     */
    public function getType() {
        return $this->_type;
    }

    /**
     * construct
     *
     * @param $url string
     * @param $title string
     * @param $date int 
     * @param $description string
     * @param $tags array string
     * @return bool TRUE - success , FALSE on error
     */
    function __construct($url='', $title='', $date=0, $description='', $tags=array()) {
        if (!empty($url)) {
            if (!$this->setUrl($url)) {
                return FALSE;
            }
        }

        if (!empty($title)) {
            if (!$this->setTitle($title)) {
                return FALSE;
            }
        }

        if ((int)$date > 0) {
            if (!$this->setDate($date)) {
                return FALSE;
            }
        }
        
        if (!empty($description)) {
            if (!$this->setDescription($description)) {
                return FALSE;
            }
        }
        
        if ( count($tags) > 0 ) {
            if (!$this->setTags($tags)) {
                return FALSE;
            }
        }
        return TRUE;
    }

    /**
     * __toString 
     * 
     * @access public
     * @return void
     */
    function __toString() {
        return "class Bookmark {title=" . $this->getTitle() .
            ", url=" . $this->getUrl() . ",date=" . $this->getDate() .
            ", description=" . $this->getDescription() .
            ", tags=" . var_export($this->_tags, TRUE) . "}\n";
    }
}
